home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / et / et3_0-a1.lha / et3 / src / Stream.C < prev    next >
C/C++ Source or Header  |  1992-07-10  |  13KB  |  778 lines

  1. #ifdef __GNUG__
  2. #pragma implementation
  3. #endif
  4.  
  5. #include "Stream.h"
  6. #include "StreamBuf.h"
  7. #include "FileBuf.h"
  8.  
  9. #include "Class.h"
  10. #include "String.h"
  11. #include "CType.h"
  12. #include "ObjArray.h"
  13. #include "OrdColl.h"
  14. #include "Error.h"
  15. #include "STREAMFILTERS/HexFilter.h"
  16. #include "STREAMFILTERS/StringFilter.h"
  17.  
  18. OStream cout(1);            // UNIX output Stream 1
  19. OStream cerr(2, 0, 0);      // UNIX output Stream 2
  20. IStream cin((int)0, &cout); // UNIX input Stream 0 tied to cout
  21.  
  22. //---- Stream ------------------------------------------------------------------
  23.  
  24. Stream::Stream(StreamBuf* s, bool dodelete)
  25. {
  26.     bp= s;
  27.     delete_StreamBuf= dodelete;
  28.     state= _good;
  29.     deepclone= FALSE;
  30.     it= 0;
  31. }
  32.  
  33. Stream::~Stream()
  34. {
  35.     if (it) {
  36.     if (all) {
  37.         all->RemovePtr(it);
  38.         if (all->Size() <= 0) {
  39.         OrdCollection *tmp= all;
  40.         all= 0;
  41.         delete tmp;
  42.         }
  43.     }
  44.     SafeDelete(it);
  45.     }
  46.     if (bp) {
  47.     bp->Finish();
  48.     if (delete_StreamBuf)
  49.         delete bp;
  50.     bp= 0;
  51.     }
  52. }
  53.  
  54. void Stream::Push(StreamBuf *s)
  55. {
  56.     if (s) {
  57.     s->SetBaseStream(bp);
  58.     bp= s;
  59.     }
  60. }
  61.  
  62. void Stream::Pop()
  63. {
  64.     if (bp) {
  65.     StreamBuf *oldsb= bp;
  66.     oldsb->Finish();
  67.     bp= oldsb->GetBaseStream();
  68.     state= _good;
  69.     delete oldsb;
  70.     }
  71. }
  72.  
  73. long Stream::tell()
  74. {
  75.     return bp->tell();
  76. }
  77.  
  78. //---- Misc --------------------------------------------------------------------
  79.  
  80. OrdCollection *Stream::all;
  81.  
  82. ObjArray *Stream::Table()
  83. {
  84.     if (it == 0) {
  85.     it= new ObjArray(10);
  86.     if (all == 0)
  87.         all= new OrdCollection;
  88.     all->Add(it);
  89.     }
  90.     return it;
  91. }
  92.  
  93. int Stream::IndexOfPtr(Object *op)
  94. {
  95.     return Table()->IndexOfPtr(op);
  96. }
  97.  
  98. Object *Stream::At(int ix)
  99. {
  100.     return Table()->At(ix);
  101. }
  102.  
  103. void Stream::AtPut(int ix, Object *op)
  104. {
  105.     if (op)
  106.     Table()->AtPutAndExpand(ix, op);
  107. }
  108.  
  109. int Stream::MakeIndex(Object *op)
  110. {
  111.     return Table()->Index(op);
  112. }
  113.  
  114. void Stream::InvalidatePtr(Object *op)
  115. {
  116.     if (all && op) {
  117.     Iter next(all);
  118.     register ObjArray *oa;
  119.     int ix;
  120.     
  121.     while (oa= (ObjArray*) next())
  122.         if (oa != op)
  123.         if ((ix= oa->IndexOfPtr(op)) >= 0)
  124.             oa->AtPut(ix, (Object*) 0x01);
  125.     }
  126. }
  127.  
  128. //---- OStream -----------------------------------------------------------------
  129.  
  130. double OStream::dd;
  131.  
  132. OStream::OStream(StreamBuf* s, bool dodelete) : Stream(s, dodelete)
  133. {
  134. }
  135.  
  136. OStream::OStream(int fd) : Stream(new Filebuf(fd), TRUE)
  137. {
  138. }
  139.  
  140. OStream::OStream(int fd, char *bp, int size) : Stream(new Filebuf(fd, bp, size), TRUE)
  141. {
  142. }
  143.  
  144. OStream::OStream(int size, char* p) : Stream(new StreamBuf(size, p), TRUE)
  145. {
  146. }
  147.  
  148. OStream::OStream(char* path) : Stream(new Filebuf(path, output), TRUE)
  149. {
  150.     if (! ((Filebuf*)bp)->isopen())
  151.     state |= _fail;
  152. }
  153.  
  154. OStream::~OStream()
  155. {
  156.     flush();
  157. }
  158.  
  159. OStream& OStream::seek(long pos, bool relative)
  160. {
  161.     if (pos == 0 && relative)
  162.     return *this;
  163.     bp->seek(pos, relative);
  164.     return *this;
  165. }
  166.  
  167. long OStream::tell()
  168. {
  169.     return bp->tell();
  170. }
  171.  
  172. OStream& OStream::flush()
  173. {
  174.     if (bp)
  175.     bp->overflow();
  176.     return *this;
  177. }
  178.  
  179. OStream& OStream::put(char c)
  180. {
  181.     if (state == 0)
  182.     if (bp->sputc(c) == EOF)
  183.         state |= _eof | _fail;
  184.     return *this;
  185. }
  186.  
  187. OStream& OStream::put(u_char b)
  188. {
  189.     if (state == 0) {
  190.     int c= b;
  191.     if (bp->sputc(c) == EOF)
  192.         state |= _eof | _fail;
  193.     }
  194.     return *this;
  195. }
  196.  
  197. OStream& OStream::form(char* va_(fmt), ...)
  198. {
  199.     if (state == 0) {
  200.     va_list ap;
  201.     va_start(ap,va_(fmt));
  202.     char *format= va_(fmt); 
  203.     char buf[BUFSIZE];
  204.     
  205.     register int ll= (int) vsprintf(buf, format, ap);
  206.     if (0 < ll && ll < BUFSIZE)                 // length
  207.         ;
  208.     else if (buf < (char*)ll && (char*)ll < buf+BUFSIZE) // pointer to trailing 0
  209.         ll= (char*)ll - buf;
  210.     else
  211.         ll= strlen(buf);
  212.     write(buf, ll);
  213.     va_end(ap);
  214.     }
  215.     return *this;
  216. }
  217.  
  218. OStream& OStream::Print(int code, void *vp)
  219. {
  220.     register StreamBuf *nbp= bp;
  221.  
  222.     if (state)
  223.     return *this;
  224.     
  225.     switch (code) {
  226.     case eTNone:
  227.     break;
  228.     case eTChar:
  229.     case eTUChar:
  230.     if (nbp->sputc((int)vp) == EOF)
  231.         state |= _fail;
  232.     break;
  233.  
  234.     case eTShort:
  235.     form("%d", (long)vp);
  236.     break;
  237.     case eTUShort:
  238.     form("%u", (u_long)vp);
  239.     break;
  240.     case eTInt:
  241.     form("%d", (long)vp);
  242.     break;
  243.     case eTUInt:
  244.     form("%u", (u_long)vp);
  245.     break;
  246.     case eTLong:
  247.     form("%ld", (long)vp);
  248.     break;
  249.     case eTULong:
  250.     form("%lu", (u_long)vp);
  251.     break;
  252.  
  253.     case eTFloat:
  254.     case eTDouble:
  255.     form("%lg", *((double*)vp));
  256.     break;
  257.  
  258.     case eTString:
  259.     case eTUString:
  260.     if (vp && *((char*)vp))
  261.         write((const char*)vp, strlen((char*)vp));
  262.     break;
  263.  
  264.     case eTStream:
  265.     register StreamBuf* b= ((Stream*)vp)->getsbuf();
  266.     register int c= b->sgetc();
  267.     while (c != EOF) {
  268.         if (nbp->sputc(c) == EOF) {
  269.         state|= _fail;
  270.         break;
  271.         }
  272.         c= b->snextc();
  273.     }
  274.     break;
  275.     case eTVoid:
  276.     form("0x%08x", vp);
  277.     fprintf(stderr, "OStream::Print: void*, be careful\n");
  278.     break;
  279.     default:
  280.     fprintf(stderr, "OStream::Print: unknown code %d\n", code);
  281.     break;
  282.     }
  283.     return *this;
  284. }
  285.  
  286. int OStream::write(const u_char *s, int n)     
  287. {
  288.     if (state || n <= 0)
  289.     return 0;
  290.     int r= bp->sputn((char*)s, n);
  291.     if (r != n)
  292.     setstate((state_value)(_eof|_fail));
  293.     return r;
  294. }
  295.  
  296. OStream &OStream::PrintString(char *s, int l)
  297. {
  298.     if (s == 0) {
  299.     (*this) << -1 SP;
  300.     } else {
  301.     if (l < 0)
  302.         l= strlen(s)+1;
  303.     (*this) << l SP;
  304.     if (0) {
  305.         put('[');
  306.         write(s, l);
  307.     } else {
  308.         put('\"');
  309.         Push(new StringEncoder);
  310.         write(s, l);
  311.         Pop();
  312.     }
  313.     }
  314.     return (*this);
  315. }
  316.  
  317. OStream &OStream::PrintHexString(char *s, int l)
  318. {
  319.     if (l < 0)
  320.     l= strlen(s)+1;
  321.     (*this) << l SP;
  322.     put('<');
  323.     Push(new HexEncoder(">"));
  324.     write(s, l);
  325.     Pop();
  326.     return (*this);
  327. }
  328.  
  329. void OStream::PutBigEndian(int bytes, long v)
  330. {
  331.     register StreamBuf *nbp= bp;
  332.     while (bytes-- > 0)
  333.     nbp->sputc((int)((v >> bytes*8) & 0xff));
  334. }
  335.  
  336. //---- IStream -----------------------------------------------------------------
  337.  
  338. IStream::IStream(StreamBuf* s, OStream* t, bool dodelete) : Stream(s, dodelete)        // bind to buffer
  339. {
  340.     tied_to= t;
  341. }
  342.  
  343. IStream::IStream(int size, char *p) : Stream(new StreamBuf(size, p, size), TRUE)    // bind to string
  344. {
  345.     tied_to= 0;
  346. }
  347.  
  348. IStream::IStream(int fd, OStream* t) : Stream(new Filebuf(fd), TRUE)        // bind to file
  349. {
  350.     tied_to= t;
  351. }
  352.  
  353. IStream::IStream(char *path) : Stream(new Filebuf(path, input), TRUE)        // bind to file
  354. {
  355.     tied_to= 0;
  356.     if (! ((Filebuf*)bp)->isopen())
  357.     state |= _fail;
  358. }
  359.  
  360. IStream& IStream::seek(long pos, bool relative)
  361. {
  362.     if (pos != 0 || !relative)
  363.     bp->seek(pos, relative);
  364.     return *this;
  365. }
  366.  
  367. long IStream::tell()
  368. {
  369.     return bp->tell();
  370. }
  371.  
  372. OStream* IStream::tie(OStream* s)
  373. {
  374.     OStream* t= tied_to;
  375.     tied_to= s;
  376.     return t; 
  377. }
  378.  
  379. void IStream::eatwhite()
  380. {
  381.     flush();
  382.     register StreamBuf *nbp= bp;
  383.     register char c= nbp->sgetc();
  384.  
  385.     while (Isspace(zapeof(c)))
  386.     c= nbp->snextc();
  387.     if (c == EOF)
  388.     state |= _eof;
  389. }
  390.  
  391. int IStream::read(u_char *s, int n)
  392. {
  393.     if (state || n <= 0) {
  394.     state |= _fail;
  395.     return 0;
  396.     }
  397.     int r= bp->sgetn((char*)s, n);
  398.     if (r < n) {
  399.     state= _fail | _eof;
  400.     }
  401.     return r;
  402. }
  403.  
  404. IStream& IStream::get(char& c)  // single character
  405. {
  406.     flush();
  407.     
  408.     if (state) {
  409.     state |= _fail;
  410.     return *this;
  411.     }
  412.     register tc= bp->sgetc();
  413.     if (tc == EOF) {
  414.     state |= _fail|_eof;
  415.     } else {
  416.     c= tc;
  417.     bp->stossc();
  418.     }
  419.     return *this;
  420. }
  421.  
  422. IStream& IStream::peek(char& c)  // single character
  423. {
  424.     flush();
  425.     
  426.     if (state) {
  427.     state |= _fail;
  428.     return *this;
  429.     }
  430.     register tc= bp->sgetc();
  431.     if (tc == EOF) {
  432.     state |= _fail|_eof;
  433.     } else {
  434.     c= tc;
  435.     }
  436.     return *this;
  437. }
  438.  
  439. IStream& IStream::peek(u_char &b)
  440. {
  441.     flush();
  442.     
  443.     if (state) {
  444.     state |= _fail;
  445.     return *this;
  446.     }
  447.     register tc= bp->sgetc();
  448.     if (tc == EOF)
  449.     state |= _fail|_eof;
  450.     else {
  451.     b= (u_char) tc;
  452.     }
  453.     return *this;
  454. }
  455.  
  456. extern "C" double atof(const char*);
  457.  
  458. IStream& IStream::Scan(int code, void *vp)
  459. {
  460.     register StreamBuf *nbp= bp;
  461.     register int c;
  462.     register long l= 0;
  463.     char buf[256];
  464.     register char *s;
  465.     int neg= 0;
  466.  
  467.     eatwhite();
  468.  
  469.     if (state) {
  470.     state |= _fail;
  471.     return *this;
  472.     }
  473.  
  474.     c= nbp->sgetc();
  475.     if (c == EOF) {
  476.     state |= _fail;
  477.     return *this;
  478.     }
  479.  
  480.     switch (code) {
  481.     case eTNone:
  482.     break;
  483.     case eTChar:
  484.     case eTUChar:
  485.     if (code == eTChar)
  486.         *((char*)vp)= c;
  487.     else
  488.         *((u_char*)vp)= c;
  489.     nbp->stossc();
  490.     break;
  491.     case eTShort:
  492.     case eTUShort:
  493.     case eTInt:
  494.     case eTUInt:
  495.     case eTLong:
  496.     case eTULong:
  497.     switch (c) {
  498.     case '-':
  499.     case '+':
  500.         neg= c;
  501.         c= nbp->snextc();
  502.         break;
  503.     }
  504.     
  505.     if (Isdigit(c)) {
  506.         do {
  507.         l= l*10+c-'0';
  508.         } while (Isdigit(c= nbp->snextc()));
  509.         l= (neg == '-') ? -l : l;
  510.         
  511.         switch (code) {
  512.         case eTShort:
  513.         *((short*)vp)= (short)l;
  514.         break;
  515.         case eTUShort:
  516.         *((u_short*)vp)= (u_short)l;
  517.         break;
  518.         case eTInt:
  519.         *((int*)vp)= (int)l;
  520.         break;
  521.         case eTUInt:
  522.         *((u_int*)vp)= (u_int)l;
  523.         break;
  524.         case eTLong:
  525.         *((long*)vp)= (long)l;
  526.         break;
  527.         case eTULong:
  528.         *((u_long*)vp)= (u_long)l;
  529.         break;
  530.         }
  531.     } else
  532.         state |= _fail;
  533.     break;
  534.  
  535.     case eTFloat:
  536.     case eTDouble:
  537.     s= buf;
  538.     switch (c) {
  539.     case '-':
  540.     case '+':
  541.         *s++= c;
  542.         c= nbp->snextc();
  543.     }
  544.     
  545.     /* get integral part */
  546.     while (Isdigit(c)) {
  547.         *s++= c;
  548.         c= nbp->snextc();
  549.     }
  550.     
  551.     /* get fraction */
  552.     if (c == '.') {
  553.         do {
  554.         *s++= c;
  555.         c= nbp->snextc();
  556.         } while (Isdigit(c));
  557.     }
  558.     
  559.     /* get exponent */
  560.     if (c == 'e' || c == 'E') {
  561.         *s++= c;
  562.         switch (c= nbp->snextc()) {
  563.         case EOF:
  564.         state|= _fail;
  565.         return *this;
  566.         case '-':
  567.         case '+':
  568.         *s++= c;
  569.         c= nbp->snextc();
  570.         }
  571.         while (Isdigit(c)) {
  572.         *s++= c;
  573.         c= nbp->snextc();
  574.         }
  575.     }
  576.     
  577.     *s= 0;
  578.     if (code == eTDouble)
  579.         *((double*)vp)= atof(buf);
  580.     else
  581.         *((float*)vp)= (float) atof(buf);
  582.     break;
  583.  
  584.     case eTString:
  585.     case eTUString:
  586.     s= (char*) vp;
  587.     while (!Isspace(c) && c != EOF) {
  588.         *s++= c;
  589.         c= nbp->snextc();
  590.     }
  591.     *s= '\0';
  592.     break;
  593.  
  594.     case eTStream:
  595.     register StreamBuf* b= ((Stream*)vp)->getsbuf();
  596.     while (c != EOF) {
  597.         if (b->sputc(c) == EOF)
  598.         break;
  599.         c= nbp->snextc();
  600.     }
  601.     break;
  602.     default:
  603.     fprintf(stderr, "IStream::Scan: unknown code %d\n", code);
  604.     break;
  605.     }
  606.     return *this;
  607. }
  608.  
  609. IStream& IStream::get(
  610.     register char* s,       // character array to read into
  611.     register int len,       // size of character array
  612.     register char term      // character that terminates input
  613. ) {
  614.     register int c;
  615.     register StreamBuf *nbp= bp;
  616.  
  617.     eatwhite();
  618.  
  619.     if (state) {
  620.     state |= _fail;
  621.     return *this;
  622.     }
  623.  
  624.     if ((c= bp->sgetc()) == EOF) {
  625.     state |= _fail | _eof;
  626.     return *this;
  627.     }
  628.  
  629.     while (c != term && c != EOF && len > 1) {
  630.     *s++= c;
  631.     c= nbp->snextc();
  632.     len--;
  633.     }
  634.     *s= '\0';
  635.     if (c == EOF)
  636.     state |= _eof;
  637.     return *this;
  638. }
  639.  
  640. IStream& IStream::putback(register char c)
  641. {
  642.     bp->sputbackc(c);
  643.     return *this;
  644. }
  645.  
  646. IStream& IStream::get(u_char &b)
  647. {
  648.     flush();
  649.     
  650.     if (state) {
  651.     state |= _fail;
  652.     return *this;
  653.     }
  654.     register tc= bp->sgetc();
  655.     if (tc == EOF)
  656.     state |= _fail|_eof;
  657.     else {
  658.     b= (u_char) tc;
  659.     bp->stossc();
  660.     }
  661.     return *this;
  662. }
  663.  
  664. long IStream::GetBigEndian(int bytes)
  665. {
  666.     register long w= 0;
  667.     register int tc;
  668.     
  669.     flush();
  670.  
  671.     if (state || bytes < 1 || bytes > 4) {
  672.     state |= _fail;
  673.     return 0;
  674.     }
  675.  
  676.     while (bytes-- > 0) {
  677.     if ((tc= bp->sgetc()) == EOF) {
  678.         state |= _fail|_eof;
  679.         return 0;
  680.     } else {
  681.         bp->stossc();
  682.         w= w*256 + tc;
  683.     }
  684.     }
  685.     return w;
  686. }
  687.  
  688. char IStream::GetChar()
  689. {
  690.     flush();
  691.     
  692.     if (state) {
  693.     state |= _fail;
  694.     return 0;
  695.     }
  696.     register tc= bp->sgetc();
  697.     if (tc == EOF) {
  698.     state |= _fail|_eof;
  699.     } else
  700.     bp->stossc();
  701.     return tc;
  702. }
  703.  
  704. u_char IStream::GetByte()
  705. {
  706.     u_char b;
  707.     flush();
  708.     
  709.     if (state) {
  710.     state |= _fail;
  711.     return 0;
  712.     }
  713.     register tc= bp->sgetc();
  714.     if (tc == EOF) {
  715.     state |= _fail|_eof;
  716.     } else {
  717.     b= tc;
  718.     bp->stossc();
  719.     }
  720.     return b;
  721. }
  722.  
  723. u_char IStream::GetHex()
  724. {
  725.     char c;
  726.     u_long val= 0;
  727.  
  728.     for (int i= 0; i < 2; ) {
  729.     get(c);
  730.     if (Isxdigit(c)) {
  731.         val= val*16 + HexValue(c);
  732.         i++;
  733.     }
  734.     }
  735.     return val;
  736. }
  737.  
  738. IStream &IStream::ReadString(char **s, int *lp)
  739. {
  740.     register u_char *p, *pp;
  741.     int l;
  742.     u_char cc;
  743.  
  744.     (*this) >> l;
  745.     if (l < 0) {
  746.     if (s)
  747.         *s= 0;
  748.     if (lp)
  749.         *lp= 0;
  750.     } else {
  751.     (*this) >> cc;
  752.     pp= p= new u_char[l];
  753.     switch (cc) {
  754.     case '[':
  755.         read(pp, l);
  756.         break;
  757.     case '"':
  758.         Push(new StringDecoder);
  759.         read(pp, l);
  760.         Pop();
  761.         break;
  762.     case '<':
  763.         Push(new HexDecoder(">"));
  764.         read(pp, l);
  765.         Pop();
  766.         break;
  767.     }
  768.     if (s)
  769.         *s= (char*)pp;
  770.     else
  771.         delete pp;
  772.     if (lp)
  773.         *lp= l;
  774.     }
  775.     return *this;
  776. }
  777.  
  778.